/*
 * LZ78.cpp

 *
 *  Created on: Jun 10, 2014
 *      Author: carlos
 */

#include "LZ78.h"
#include "Diccionario.h"
#include "../../../utils/StringUtils.h"
LZ78::LZ78() {

}

void LZ78::compimir(string pathSource, string pathDest) {
		cout<<"comprimiendo con lz78"<<endl;
		Diccionario diccionario;

		FileReader fr(pathSource,false);
		FileWritter fw(pathDest);
		string nuevaEntradaTabla;
		while (fr.hasNext()){
			char myChar=fr.readByte();
			//cout<<myChar<<endl;
			nuevaEntradaTabla.append(StringUtils::charToString(myChar));
			if(!diccionario.isInTable(nuevaEntradaTabla)){
				unsigned int tamanioTabla=(unsigned int)log2(diccionario.getSize())+1;
				diccionario.append(nuevaEntradaTabla);
				string entradaAEmitir=nuevaEntradaTabla.substr(0,nuevaEntradaTabla.length()-1);
				nuevaEntradaTabla=nuevaEntradaTabla.substr(nuevaEntradaTabla.length()-1,nuevaEntradaTabla.length());
				//cout<<"emision: "<<diccionario.getCodigo(entradaAEmitir)<<" "<<entradaAEmitir<<endl;
				fw.write(diccionario.getCodigo(entradaAEmitir),tamanioTabla);

			}
		}
}

void LZ78::descompimir(string pathSource, string pathDest) {
	cout<<"descomprimiendo con lz78"<<endl;
	Diccionario diccionario;
	FileReader fr(pathSource,true);

	fstream archivo;
	archivo.open(pathDest.c_str(), std::ios::out | std::ios::binary);


	int codigoAnterior=8;//diccionario.getSize();
	string emitidoPasoAnterior="";
	while(fr.hasNext()){
		unsigned int tamnioTabla=(unsigned int)log2(diccionario.getSize())+1;
		int codigo=fr.readCompressedCode(codigoAnterior,tamnioTabla);
		string emisionActual="";
		if(diccionario.isInTableCode(codigo)){
			emisionActual=diccionario.getValue(codigo);
			//cout<<emisionActual<<endl;
			archivo<<emisionActual;
			string stringAgregarTabla=emitidoPasoAnterior.append(emisionActual.substr(0,1));
			diccionario.append(stringAgregarTabla);
			emitidoPasoAnterior=emisionActual;
			codigoAnterior=diccionario.getCodigo(stringAgregarTabla);

		}else{//caso especial
			emisionActual=emitidoPasoAnterior;
			emisionActual.append(emisionActual.substr(0,1));
			diccionario.append(emisionActual);
			//cout<<emisionActual<<endl;
			archivo<<emisionActual;
			emitidoPasoAnterior=emisionActual;
			codigoAnterior=diccionario.getCodigo(emisionActual);
		}
		break;
	}

		archivo.close();

}

LZ78::~LZ78() {
}

